package com.inbound;

import com.OtaService;
import com.object.Gprs;
import com.NettyServer;
import com.object.OtaObject;
import com.object.OtaTarget;
import com.util.MyUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import com.util.ProtocolUtil;
public class ProtocolDispatcherHandler extends ChannelInboundHandlerAdapter{
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception{
        // TODO: this is test
        Gprs gprs = getGprs(ctx);
        MyUtil.printMsg(gprs.getId(), (ByteBuf)msg);

        doDispatch(ctx, msg);
        ctx.fireChannelRead(msg);
    }



    private void doDispatch(ChannelHandlerContext ctx, Object msg) throws Exception{
        byte cmdIdentity = ((ByteBuf)msg).getByte(((ByteBuf) msg).readerIndex() + ProtocolUtil.HOST_SERVER_FRAME_TYPE_OFFSET);
        switch (cmdIdentity){
            case ProtocolUtil.KEEP_ALIVE:  // 心跳保活帧
                ctx.write(msg); // 心跳直接回复
                // TODO: test
                //startUpgrade(ctx);
                break;
            case ProtocolUtil.ACK:   // 指令应答帧
                ackResponseDispatch(ctx, msg);
                break;
            case ProtocolUtil.UPGRADE_RESULT:
                upgradeResult(ctx, msg);
                break;
            case ProtocolUtil.ERROR_CONNECTION:
                getGprs(ctx).errorConnectionProcess(getDataBytes(msg));
                break;

        }
    }

    private Gprs getGprs(ChannelHandlerContext ctx){
        return ctx.channel().attr(NettyServer.GPRS).get();
    }
    private byte[] getDataBytes(Object msg){
        ByteBuf in = (ByteBuf)msg;
        byte[] dataFrame = new byte[in.readableBytes() - ProtocolUtil.HOST_SERVER_FRAME_HEADER_TAIL_LENGTH];
        in.skipBytes(ProtocolUtil.HOST_SERVER_DATA_BEGIN_OFFSET).readBytes(dataFrame,0,dataFrame.length);
        return dataFrame;
    }

    private void upgradeResult(ChannelHandlerContext ctx, Object msg){
        ByteBuf in = (ByteBuf)msg;
        byte[] dataFrame = getDataBytes(msg);
        OtaService otaService = getGprs(ctx).getOtaService();
        if (otaService == null)
            otaService = NettyServer.GPRS_OTASERVICE.get(getGprs(ctx).getId());
        otaService.getUpgradeResult(dataFrame);

    }



    private void ackResponseDispatch(ChannelHandlerContext ctx, Object msg){
        ByteBuf in = (ByteBuf)msg;
        byte cmdIdentity = in.getByte(in.readerIndex() + ProtocolUtil.HOST_SERVER_DATA_BEGIN_OFFSET);
        switch(cmdIdentity){
            case ProtocolUtil.PKT_RQ: // 分包请求的应答，即升级请求的应答
                byte reply = in.getByte(in.readerIndex() + ProtocolUtil.HOST_SERVER_DATA_BEGIN_OFFSET + 1);
                getGprs(ctx).getOtaService().getUnpackRequestReply(reply);
                break;
            case ProtocolUtil.PKT: // 分包数据的应答，即升级程序的分包数据应答

                // 获取包序号
                byte[] indexBytes = new byte[ProtocolUtil.UPGRADE_UNPACK_FRAME_BYTE_LENGTH];
                in.getBytes(in.readerIndex() + ProtocolUtil.HOST_SERVER_DATA_BEGIN_OFFSET + 1, indexBytes, 0, indexBytes.length );
                int index = MyUtil.getUInt16(indexBytes);

                getGprs(ctx).getOtaService().getPackFrameReply(index,in.getByte(in.readerIndex() +
                ProtocolUtil.HOST_SERVER_DATA_BEGIN_OFFSET + ProtocolUtil.UPGRADE_UNPACK_FRAME_BYTE_LENGTH + 1));
                break;
        }

    }

    // TODO: test above
    private void startUpgrade(ChannelHandlerContext ctx) throws Exception{
        OtaObject ob = new OtaObject();
        ob.otaTarget = OtaTarget.STM_HOST;
        ob.binFilePath = "C:\\Users\\PuliTech\\Documents\\GeorgeCaoJ\\GPRS后台接收客户端\\docs\\base_master_BLE.bin";
        ob.firmware = 31;
        ob.version = 31;
        Gprs gprs = ctx.channel().attr(NettyServer.GPRS).get();
        gprs.initialOtaService();
        gprs.getOtaService().setOtaObject(ob).startUpgrade();
    }

}
